package parsedata

import (
	"encoding/csv"
	"fmt"
	"log"
	"math"
	"os"
	"strconv"

	"gonum.org/v1/gonum/mat"
)

func ParseCSV(path string) (*mat.Dense, []string, error) {
	matrix, names, err := fileToMatrix(path)
	if err != nil {
		return nil, nil, err
	}
	log.Println("Размерность данных до первичной обработки: ", matrix.RawMatrix().Rows, "x", matrix.RawMatrix().Cols)
	cleanMatrix(matrix)
	log.Println("Размерность данных после удаления неполных строк: ", matrix.RawMatrix().Rows, "x", matrix.RawMatrix().Cols)
	return matrix, names, nil
}

func fileToMatrix(path string) (*mat.Dense, []string, error) {
	file, err := os.Open(path)
	if err != nil {
		log.Println(err)
		return nil, nil, err
	}
	defer file.Close()

	reader := csv.NewReader(file)
	records, err := reader.ReadAll()
	if err != nil {
		log.Println(err)
		return nil, nil, err
	}

	names := records[0]

	records = records[1:]

	// преобразование в матрицу

	rows, cols := len(records), len(records[0])
	data := make([]float64, rows*cols)

	brands := make(map[string]int, 0)
	countsBrands := 0

	for i, record := range records {
		for j, strValue := range record {
			if j == 0 {
				v, res := brands[strValue]
				if !res {
					brands[strValue] = countsBrands
					data[i*cols+j] = float64(countsBrands)
					countsBrands++
				} else {
					data[i*cols+j] = float64(v)
				}
				continue
			}

			value, err := strconv.ParseFloat(strValue, 64)
			if err != nil {
				if i*j != 0 {
					log.Println("Record: ", i, " Column: ", j, "\n", err)
				}
				data[i*cols+j] = math.NaN()
			}
			data[i*cols+j] = value
		}
	}

	//data = data[:10]
	//fmt.Println(data)

	matrix := mat.NewDense(rows, cols, data)
	return matrix, names, nil
}

func cleanMatrix(matrix *mat.Dense) {
	//
	//
	//

	cols := matrix.RawMatrix().Cols - 1

	for i := 0; i < matrix.RawMatrix().Rows; i++ {
		matrix.Set(i, cols, float64(int(matrix.At(i, cols))/1000*1000))
		fmt.Println(matrix.At(i, cols))
	}
}
